home *** CD-ROM | disk | FTP | other *** search
/ Best of Shareware / Best of PC Windows Shareware 1.0 - Wayzata Technology (7111) (1993).iso / mac / DOS / PROGRAMG / FORTHCMP / DRIVER.4TH < prev    next >
Text File  |  1992-03-30  |  7KB  |  253 lines

  1. \ Example code for a device driver
  2. \ See Advanced MSDOS Programming, by Ray Duncan (Microsoft Press)
  3. \  for details of driver writing
  4.  
  5. \ You can use this driver as a skeleton. It is set up as a demonstration
  6. \ character device driver which consists of a circular buffer that can
  7. \ be read and written. But all entry point routines are provided
  8.  
  9.  
  10. 0 DRIVER
  11. 24 CONSTANT MaxCmd    \ number of commands to respond to in table
  12.  
  13. HEX
  14. H: RETF  0CB C, ;    \ Far return instruction for assembler
  15.  
  16. NEED Strat  NEED Intr
  17.  
  18.  
  19. -1 , -1 ,    \ driver header
  20. 08800 ,        \ device attribute word, "generic" driver for DOS 3 or later
  21. ', Strat        \ strategy routine offset
  22. ', Intr         \ interrupt routine offset
  23. ," SKELETON"    \ eight character device name
  24.  
  25. 2VARIABLE RHPtr    \ segment/offset of request
  26.  
  27. \ Dispatched functions will return STATUS, with "done" bit set 
  28. \ automatically (this means that most functions will return 0)
  29.  
  30. 0 1 IN/OUT  NEED Init 
  31. 0 1 IN/OUT  NEED MediaChk 
  32. 0 1 IN/OUT  NEED BuildBPB 
  33. 0 1 IN/OUT  NEED IoctlRd 
  34. 0 1 IN/OUT  NEED Read 
  35. 0 1 IN/OUT  NEED NdRead 
  36. 0 1 IN/OUT  NEED InpStat 
  37. 0 1 IN/OUT  NEED InpFlush
  38. 0 1 IN/OUT  NEED Write 
  39. 0 1 IN/OUT  NEED WriteVfy 
  40. 0 1 IN/OUT  NEED OutStat 
  41. 0 1 IN/OUT  NEED OutFlush
  42. 0 1 IN/OUT  NEED IoctlWt 
  43. 0 1 IN/OUT  NEED DevOpen 
  44. 0 1 IN/OUT  NEED DevClose 
  45. 0 1 IN/OUT  NEED RemMedia
  46. 0 1 IN/OUT  NEED OutBusy 
  47. 0 1 IN/OUT  NEED Error 
  48. 0 1 IN/OUT  NEED GenIOCTL 
  49. 0 1 IN/OUT  NEED GetLogDev
  50. 0 1 IN/OUT  NEED setLogDev
  51.  
  52.  
  53. CREATE Dispatch  \ dispatch table for commands, Error entries are invalid
  54. ', Init ', MediaChk ', BuildBPB ', IoctlRd 
  55. ', Read ', NdRead ', InpStat ', InpFlush
  56. ', Write ', WriteVfy ', OutStat ', OutFlush
  57. ', IoctlWt ', DevOpen ', DevClose ', RemMedia
  58. ', OutBusy ', Error ', Error ', GenIOCTL 
  59. ', Error ', Error ', Error ', GetLogDev
  60. ', setLogDev
  61.  
  62. CODE Strat    \ Strategy routine just saves request block address
  63.     BX CS: RHPtr [] MOV
  64.     CS: RHPtr 2+ [] ES <SEG
  65.     RETF 
  66. END-CODE
  67.  
  68. \ handle data/stack memory needed for Forth
  69. VARIABLE DP       ( start free ram = HERE )
  70. VARIABLE S0       ( top of stack )
  71. VARIABLE R0       ( top of return stack )
  72. VARIABLE BASE  0A BASE ! ( initialized at compile time )
  73.  
  74. 2VARIABLE OLDSTACK
  75.  
  76. 80 ALLOT HERE S0 ! ( parameter stack -- may need to be bigger )
  77. 80 ALLOT HERE R0 ! ( return stack--may need to be bigger )
  78.  
  79. 0 0 IN/OUT  NEED INTR
  80.  
  81. CODE Intr
  82.     AX PUSH BX PUSH CX PUSH DX PUSH SI PUSH DI PUSH BP PUSH
  83.     DS PUSHSEG ES PUSHSEG    \ save all but stack here
  84.     AX CS <SEG AX DS >SEG    \ establish adressability
  85.     
  86.     OLDSTACK 2+ [] SS <SEG   SP OLDSTACK [] MOV \ save old stack
  87.     AX SS >SEG
  88.     S0 @ # SP MOV    \ set new stack
  89.     R0 @ # BP MOV    \ and return stack
  90.  
  91.     RHPtr [] DI LES    \ command block
  92.     ES: 2 +[DI] BL MOV  \ command code
  93.     BH BH XOR  
  94.     MaxCmd # BX CMP >S ~ IF,    \ command in range
  95.         BX 1 SHL  Dispatch +[BX] CALLI
  96.     ELSE,
  97.         CALL' Error
  98.     THEN,
  99.     RHPtr [] DI LES    \ command block
  100.     100 # AX OR  AX  ES: 3 +[DI] MOV    \ set status field
  101.     
  102.     OLDSTACK 2+ [] SS >SEG   OLDSTACK [] SP MOV \ restore old stack
  103.     ES POPSEG DS POPSEG
  104.         BP POP DI POP SI POP DX POP CX POP BX POP AX POP
  105.     RETF
  106. END-CODE
  107.  
  108.  
  109. \ Default routines -- these return "success" 
  110. \  since there is no code inside, they will fall through to the commmon
  111. \  code in the last definition, which is made a colon definition.
  112. \  If you intend to have the function actually do something, then
  113. \  move the definition elsewhere!
  114.  
  115.  
  116.  
  117. CODE MediaChk     END-CODE    \ not used for character devices-- return done
  118. CODE BuildBPB     END-CODE    \ not used for character devices-- return done
  119. CODE IoctlRd     END-CODE    \ disabled in header word
  120. \ CODE Read     END-CODE    \ implemented below
  121. \ CODE NdRead     END-CODE    \ implemented below
  122. \ CODE InpStat     END-CODE    \ implemented below
  123. \ CODE InpFlush    END-CODE    \ implemented below
  124. \ CODE Write     END-CODE    \ implemented below
  125. \ CODE WriteVfy END-CODE    \ implemented below
  126. \ CODE OutStat     END-CODE    \ implemented below
  127. \ CODE OutFlush    END-CODE    \ Not used in this example -- always success
  128. CODE IoctlWt     END-CODE    \ disabled in header word
  129. CODE DevOpen     END-CODE    \ disabled in header word
  130. CODE DevClose     END-CODE    \ disabled in header word
  131. CODE RemMedia    END-CODE    \ disabled in header word
  132. CODE OutBusy     END-CODE    \ disabled in header word
  133. CODE GenIOCTL     END-CODE    \ disabled in header word
  134. CODE GetLogDev    END-CODE    \ not used for character devices-- return done
  135. CODE setLogDev    END-CODE    \ not used for character devices-- return done
  136. 0 1 IN/OUT
  137. : SUCCESS  0 ;
  138.  
  139. \ The error routine for invalid codes
  140. : Error  8003 ;
  141.  
  142. \
  143. \ The actual SKELETON device driver follows.
  144. \
  145.  
  146. CREATE CIRBUF 100 ALLOT    \ the circular buffer
  147. HERE CONSTANT CIREND
  148.  
  149. VARIABLE INPTR  CIRBUF INPTR !        \ pointer for reading
  150. VARIABLE OUTPTR  CIRBUF OUTPTR !    \ pointer for writing
  151. VARIABLE TMP
  152. VARIABLE TMP2
  153.  
  154. : Read         \ read characters, returns control-Z at "End of File"
  155.         \ since otherwise this driver would hang forever!
  156.     TMP OFF    \ use for read count
  157.     RHPtr 2@ 2DUP 0E + 2@L 2SWAP 12 + @L    \ farbuffer addr and length
  158.     0 ?DO   1 TMP +!    
  159.         INPTR @ OUTPTR @ = IF \ nothing left
  160.             2DUP CONTROL Z -ROT C!L    \ indicate EOF
  161.             LEAVE THEN
  162.         2DUP INPTR @ C@ -ROT C!L \ store the character
  163.         1+    \ increment farbuffer pointer
  164.         INPTR @ 1+ DUP CIREND =     \ circularly increment INPTR
  165.             IF DROP CIRBUF THEN INPTR ! 
  166.     LOOP
  167.     2DROP    \ the buffer address
  168.     TMP @  RHPtr 2@ 12 + !L    \ actual characters read
  169.     0 
  170. ;
  171.  
  172. : NdRead    \ peek for any available character
  173.     INPTR @ OUTPTR @ <> IF \ character available
  174.         INPTR @ C@  RHPtr 2@ 0D + C!L \ get the character
  175.         0    \ returns status saying it is available
  176.         EXIT
  177.     THEN
  178.     200    \ return busy bit set -- no character available
  179. ;
  180.  
  181. : InpStat    \ check for available character
  182.     INPTR @ OUTPTR @ <> IF \ character available
  183.         0
  184.         EXIT
  185.         THEN
  186.     200    \ return busy bit set if none available
  187. ;
  188.  
  189. : InpFlush    \ Flush input buffer -- here, discards all available data
  190.     INPTR @ OUTPTR !
  191. ;
  192.  
  193. CODE WriteVfy END-CODE    \ do Write for WriteVfy
  194.  
  195. : Write        \ write characters to buffer -- give error if we overflow
  196.     TMP OFF    \ use for write count
  197.     TMP2 OFF    \ set if error
  198.     RHPtr 2@ 2DUP 0E + 2@L 2SWAP 12 + @L    \ farbuffer addr and length
  199.     0 ?DO   1 TMP +!    
  200.         2DUP C@L OUTPTR @ C! \ store the character
  201.         1+    \ increment farbuffer pointer
  202.         OUTPTR @ 1+ DUP CIREND =     \ circularly increment OUTPTR
  203.             IF DROP CIRBUF THEN
  204.         DUP INPTR @ = IF \ trouble -- buffer overflows
  205.             800A TMP2 !    \ Write error
  206.             -1 TMP +!
  207.             DROP
  208.             LEAVE THEN
  209.         OUTPTR !    \ success!
  210.     LOOP
  211.     2DROP    \ the buffer address
  212.     TMP @  RHPtr 2@ 12 + !L    \ actual characters read
  213.     TMP2 @  \ return error code
  214. ;
  215.  
  216. : OutStat    \ Output status -- can we write?
  217.     OUTPTR @ 1+ DUP CIREND = IF DROP CIRBUF THEN INPTR @ = IF
  218.         200 \ set busy bit if buffer is full
  219.         EXIT
  220.         THEN
  221.     0
  222. ;
  223.  
  224. INCLUDE FORTHLIB
  225. HEX
  226.  
  227. \
  228. \ INITIALIZATION CODE
  229. \
  230. \ What follows will be not be part of the file after installing
  231. \  the driver.
  232.  
  233. CODE EMIT    \ rewrite EMIT to use acceptable system call
  234.     AL DL MOV
  235.     2 # AH MOV
  236.     21 INT
  237.     RET
  238. END-CODE
  239.  
  240. : Init 
  241.     ." Skeleton driver -- Just for demonstration" CR
  242.     ." Loaded at " HEX ?CS: 0 <# # # # # #> TYPE ." :0000" CR
  243.     ." Size is " ['] EMIT DECIMAL  U. ." (decimal) bytes." CR
  244.     ." But is " HERE U. ." bytes at load time." CR
  245.  
  246.     ?CS: ['] EMIT RHPtr 2@ 0E + 2!L    \ store address of driver end
  247.  
  248.     0
  249. ;
  250.  
  251. INCLUDE FORTHLIB   \ read it in again to resolve extra functions
  252. END
  253.